package com.gitee.srurl.system.biz;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.mutable.MutablePair;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gitee.srurl.core.constant.GlobalConstant;
import com.gitee.srurl.core.domain.SusUserDomain;
import com.gitee.srurl.core.enums.ResponseCodeEnums;
import com.gitee.srurl.core.exception.ServiceException;
import com.gitee.srurl.core.exception.login.LoginFailException;
import com.gitee.srurl.core.service.ISusUserService;
import com.gitee.srurl.core.util.CryptoUtil;
import com.gitee.srurl.core.util.JwtUtil;
import com.gitee.srurl.core.util.RsaUtil;
import com.gitee.srurl.core.util.login.LoginHelper;
import com.gitee.srurl.core.util.login.OperationUser;
import com.gitee.srurl.system.params.LoginParams;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @author zxw
 * @date 2023/5/3 14:49
 */
@Component
@RequiredArgsConstructor
public class LoginBiz {

    private final ISusUserService userService;

    /**
     * 登录
     *
     * @param loginParams 登录参数
     * @param apiLogin    是否api登录（如果需要上验证码啥的 可以在api这边放开 无验证码只允许api用户登录等）
     * @return token参数
     */
    public Map<String, Object> login(LoginParams loginParams, boolean apiLogin) {

        SusUserDomain user;
        if (apiLogin) {
            user = this.apiUserLogin(loginParams);
        } else {
            user = this.userLogin(loginParams);
        }

        OperationUser operationUser = new OperationUser();
        operationUser.setApi(apiLogin);
        operationUser.setUsername(user.getUsername());
        operationUser.setUserId(user.getId());
        MutablePair<String, DateTime> pair = JwtUtil.genJwtToken(operationUser);
        Map<String, Object> map = new HashMap<>();
        String token = pair.getKey();
        DateTime expireTime = pair.getValue();
        map.put("token", token);
        map.put("expireTime", expireTime.toString("yyyy-MM-dd HH:mm:ss"));
        map.put("userId", user.getId());
        map.put("username", user.getUsername());

        return map;
    }

    private SusUserDomain userLogin(LoginParams loginParams) {
        SusUserDomain user;
        String username = loginParams.getUsername();
        String password = loginParams.getPassword();
        if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {
            throw new ServiceException("登录参数不能为空！");
        }
        LambdaQueryWrapper<SusUserDomain> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(SusUserDomain::getUsername, username);
        SusUserDomain userDomain = userService.getOne(userQueryWrapper);

        user = this.userLoginCheck(loginParams, userDomain);
        return user;
    }

    private SusUserDomain apiUserLogin(LoginParams loginParams) {
        SusUserDomain user;
        String apiKey = loginParams.getApiKey();
        String password = loginParams.getPassword();
        if (StrUtil.isBlank(apiKey) || StrUtil.isBlank(password)) {
            throw new ServiceException("登录参数不能为空！");
        }
        LambdaQueryWrapper<SusUserDomain> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(SusUserDomain::getApiKey, apiKey);
        SusUserDomain userDomain = userService.getOne(userQueryWrapper);

        user = this.userLoginCheck(loginParams, userDomain);
        return user;
    }

    private SusUserDomain userLoginCheck(LoginParams loginParams, SusUserDomain userDomain) {

        if (userDomain == null) {
            throw new LoginFailException(ResponseCodeEnums.USER_OR_PASSWORD_ERROR);
        }
        if (!StrUtil.equals(userDomain.getStatus(), "1")) {
            throw new LoginFailException(ResponseCodeEnums.USER_ACCOUNT_DISABLE);
        }
        if (!CryptoUtil.passwordMatches(RsaUtil.decrypt(loginParams.getPassword()), userDomain.getPassword())) {
            throw new LoginFailException(ResponseCodeEnums.USER_OR_PASSWORD_ERROR);
        }

        return userDomain;
    }

    public void logout() {

        // 退出登录 目前项目使用jwt 没有做其他验证 所以没有其他操作
    }
}
